﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algobox.JuicyLib.Apps.Liquid
{
    public class CanadianDMAFile
    {
        public CanadianDMAFile(string dbConn)
        {
            JuicyLib.SQL.LiquidView.LiquidViewHelper.LiquidViewLinq = new SQL.LiquidView.LiquidViewLinqDataContext(dbConn);
        }

        const char SEPERATOR_COL = ',';
        const int COLUMNS = 12;
        const int IX_ACCOUNT = 3;
        const int IX_QUANTITY = 4;
        const int IX_PRICE = 5;
        const int IX_SYMBOL = 7;
        const int IX_SIDE = 12;

        const string HOSTNAME = "MANUAL";
        const string ORDER_ID_PREFIX = "CANADIAN";
        const string EXCHANGE = "XTSE";
        
        public bool ImportStockFile(string filename, DateTime fileDate, int skipRows)
        {
            int countMissing = 0;
            int countSuccess = 0;
                        
            List<string> tradeKeys = null;
            try
            {
                // try and load all trade identifiers for this trade date to insure we don't import dupes
                tradeKeys = JuicyLib.SQL.LiquidView.LiquidViewHelper.LiquidViewLinq.Trades.Where(x => x.Host == HOSTNAME && x.TradeTime > fileDate && x.TradeTime < fileDate.AddDays(1) && x.HostOrderId.Contains(ORDER_ID_PREFIX)).Select(t => t.HostOrderId).ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to load trade identifiers for host {0}, cannot continue with this file. Exception({1})", HOSTNAME, e);
                return false;
            }

            string[] data;
            try
            {
                data = System.IO.File.ReadAllLines(filename);
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to load file '{0}'. Exception({1})", filename, e);
                return false;
            }

            try
            {
                var query = from csvline in data
                            let csv = csvline.Split(SEPERATOR_COL)
                            where csv.Length >= COLUMNS
                            select new
                            {
                                Account = csv[IX_ACCOUNT],
                                Side = csv[IX_SIDE],
                                Symbol = csv[IX_SYMBOL],
                                Quantity = csv[IX_QUANTITY],
                                Price = csv[IX_PRICE]
                            };

                decimal price;
                long quantity;
                string orderId;
                DateTime tradeTime = fileDate.AddHours(8);

                var enumerableQuery = query.GetEnumerator();
                for (int i = 0; enumerableQuery.MoveNext(); i++)
                {
                    if (i < skipRows)
                        continue;

                    var row = enumerableQuery.Current;

                    if (String.IsNullOrEmpty(row.Account.Trim()))
                        continue;

                    try
                    {
                        orderId = String.Format("{0}-{1:yyyyMMdd}-{2:000}", ORDER_ID_PREFIX, fileDate, i);

                        // if trade exists then continue
                        if (tradeKeys.Contains(orderId))
                            continue;
                        
                        ++countMissing;

                        // quantity
                        if (!Int64.TryParse(row.Quantity, out quantity))
                        {
                            Console.WriteLine("Row {0}: Can't parse quantity {1}", i, row.Quantity);
                            continue;
                        }

                        // quantity side
                        if (row.Side != "BUY")
                            quantity = -quantity;

                        // price
                        if (!Decimal.TryParse(row.Price, out price))
                        {
                            Console.WriteLine("Row {0}: Can't parse price {1}", i, row.Price);
                            continue;
                        }
                        int result = -1;

                        // insert trade into the database
                        result = Algobox.JuicyLib.SQL.LiquidView.LiquidViewHelper.LiquidViewLinq.ImportTradeBySterlingSymbol(
                            HOSTNAME,
                            orderId,
                            orderId,
                            EXCHANGE,
                            orderId,
                            orderId,
                            row.Account,
                            null,
                            row.Symbol,
                            quantity,
                            price,
                            tradeTime,
                            HOSTNAME,
                            false,
                            false,
                            false,
                            null,
                            ORDER_ID_PREFIX + " imported from " + filename,
                            false,
                            null,
                            null,
                            null,
                            null,
                            tradeTime,
                            null);

                        if (result == 0)
                        {
                            ++countSuccess;
                            Console.WriteLine("Success ImportTradeBySterlingSymbol Returned({6}) Account({0}) Symbol({1}) Quantity({2}) Price({3}) TradeTime({4}) OrderId({5})", row.Account, row.Symbol, row.Quantity, row.Price, tradeTime, orderId, result);
                        }
                        else
                        {
                            Console.WriteLine("Failed ImportTradeBySterlingSymbol Returned({6}) Account({0}) Symbol({1}) Quantity({2}) Price({3}) TradeTime({4}) OrderId({5})", row.Account, row.Symbol, row.Quantity, row.Price, tradeTime, orderId, result);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Failed to import trade on row {0}!\r\n{1}", i, e);
                        continue;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to extract data from csv format. Exception({0})", e);

                return false;
            }

            Console.WriteLine("Successfully imported {0} trades", countSuccess);

            return true;
        }

    }
}
